#!C:\WebServer\Python2.4\python.exe

import SyntaxParser
import SQLGenerator
import datetime
import statistic
import cgi
from time import strftime
from DatabaseConnector import connection

print "Content-Type: text/html\n\n"
print """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>
	<head>
		<title>CliniDAL Results</title>
		<style type="text/css">
			body {
				font-family: Verdana, Tahoma, Sans-serif;
				font-size: 10pt;
			 	margin-top: 0;
			 	margin-left: 0;
			}
			
			div.title {
			 	float:right;
				font-weight:bold;
				margin-top: 18px;
				clear: left;
				padding-right: 20px;
				color:#FFFFFF;
				background-color: #39638B
			}
			
			#banner {
			 	margin-top: 0;
			 	margin-left: 0;
			 	background-image: url('images/top_banner_in02.gif');
			 	background-position: 227px;
				background-repeat: no-repeat;
				background-color:#39638B; 
			}
			
			#title {
			 	font-family: Arial, Tahoma, Sans-serif;
			 	margin-top: 10px;
			 	margin-left: 5px;
			 	margin-bottom: 10px;
			 	font-weight: bold;
			 	font-size: 12pt;
			}
			
			#cdal {
				margin-left: 5px;
			}
			
			#cdal_title, #results_title {
				font-weight: bold;
				color: navy;
			}
			
			#cdal_content {
			 	margin-top: 5px;
			 	width: 600px;
			 	font-family: "courier new", mono;
			 	border-style: solid;
			 	border-width: 1px;
			 	border-color: grey;
			}
			
			#results, #sqlscript, #cdal_version {
			 	margin-left: 5px;
			 	margin-top: 5px;
			}
            
            #sqlscript {
            	color: blue;
            	font-size: 9pt;
            }
            
			div.stat_answer_required, div.ref_answer_required {
			 
			}
		
			div.stat_answer_content {
			 	font-size: 8pt;
			 	font-weight: normal;
			 	color: red;
			}
	
			table {
			 	border-collapse: collapse;
			 	width: 100%;
			 	WORD-BREAK:BREAK-ALL;
			}
			
			th {
				align: left;
				font-size: 10pt;
			 	font-weight: bold;
			}
			
			td {
				align: left;
				font-size: 9pt;
			}
			
			div.stat_answer_required, div.ref_answer_required {
			 	margin-top: 5px;
			}
			
			div.ref_answer_content {
			 	font-size: 8pt;
			 	margin-top: 5px;
			 	text-align: center;
			}
			
			div.generate_csv_file {
			 	margin-top: 5px;
			 	text-align: left;
			}
			
			#errors, #db_error, #answers_error, #global_time_period_error, #global_location_error, #demo_criterias_error, #diag_error, #med_criterias_error, #cdal_error {
			 	font-size: 8pt;
			 	font-weight: normal;
			 	color: red;
			}
			
			#resultsize_error {
				margin-top: 15px;
				margin-left: 5px; 
				font-size: 12pt;
			 	font-weight: bold;
			 	color: black;
			}
			.cdal_error {
			 	font-size: 10pt;
			 	font-weight: normal;
			 	margin-left: 5px;
			 	color: red;
			}
			
			#link {
			 	float: right;
			 	margin-right: 5px;
			}
		</style>
	</head>
	
	<body>
		<div id='banner'>
			<div class='title'>
				Clinical Data Mining Project Group
			</div>
		  	<div> 
				<a href='http://www.usyd.edu.au'>
					 <img src='images/top_banner_in01.gif' width='227' height='52' alt='The University of Sydney' style='border: 0px;' class='decor' /> 
				</a>
			</div>
		</div>
		<div id='link'>
			<a href='cdal.py'>New search</a>
		</div>
		<div id='title'>
			CDAL Results
		</div>
"""

path = 'doc/interface/toc_list.txt'
toc_array = SyntaxParser.buildArray(path)
path = 'doc/interface/databases.txt'
standard_databases = SyntaxParser.buildArray(path)    
path = 'doc/interface/ref_entities.txt'
reference_entities = SyntaxParser.buildArray(path)
path = 'doc/interface/sta_entities.txt'
stat_entities = SyntaxParser.buildArray(path)
path = 'doc/interface/result_att.txt'
value_entities = SyntaxParser.buildHash(path)
path = 'doc/interface/med_entities.txt'
med_entities = SyntaxParser.buildHash(path)
path = 'doc/interface/demo_entities.txt'
demo_entities = SyntaxParser.buildHash(path)
accession_dic = {}
cursor = connection.cursor()
cursor.execute("select requestid, accessionnumber from hosrep.request_table")
for tuple in cursor:
	accession_dic[tuple[0]]=tuple[1]
#------------------------------------------------
# --------- definitions of CDAL -----------

comparands = [">",">=","<","<=","=","<>"]
types = ["and", "or"]
ref_fns = ["all values", "any value", "last value"] # yet to implement last value
stat_fns = ["mean", "sd", "median", "max", "min", "range", "mode", "sum", "count"] # yet to implement sum and count
keywords = [" whose ", " with ", " have ", " during ", " in ", " from ", " to "]

time_ent_start = ""
time_ent_end = ""
toc = ''
db = ''
answer = ''
form = cgi.FieldStorage()
cdal = str(form.getvalue("cdal"))
cdal_error_array = []
patient = ''
cond = ''
diagnosis = ''
showMRN = 0
showMRNstring = str(form.getvalue("showMRN"))
if showMRNstring == 'on':
    showMRN = 1

#------------------STARTING SYNTAX CHECKING FOR CDAL---------------------------
#CHECKING TOC
current_start_index = 0
current_end_index = cdal.find(" ")
current_string = cdal[current_start_index:current_end_index].strip()
if current_string.upper() != 'USING':    
	error = 'Syntax Error in TOC: missing USING keyword'              
	cdal_error_array.append(error)
	
current_start_index = current_end_index
current_end_index = cdal.lower().find(" in ", current_start_index)

if current_end_index == -1:
	error = 'Syntax Error in DB: missing IN keyword'
	cdal_error_array.append(error)
else:
	current_string = cdal[current_start_index:current_end_index].strip()
	has_toc_ent = 0
	for toc_entity in toc_array:
		if current_string == toc_entity.lower():
			has_toc_ent = 1
			break
	if has_toc_ent == 0:
		error = 'Syntax Error in TOC: missing|incorrect TOC'
#		print current_string
		cdal_error_array.append(error)
	else:
		#GETTING TOC
		toc = current_string
	
#CHECKING DATABASE
current_start_index = current_end_index + len(" in ")
current_end_index = cdal.lower().find(" find ", current_start_index)
if current_end_index == -1:
	error = 'Syntax error in ANSWERS: missing FIND keyword'
	cdal_error_array.append(error)
else:
	current_string = cdal[current_start_index:current_end_index].strip()
	has_db_ent = 0
	for standard_database in standard_databases:
		if current_string.upper() == standard_database.upper():
			has_db_ent = 1
			break
	if has_db_ent == 0:
		error = 'Syntax Error in DB: missing|incorrect database'
		cdal_error_array.append(error)
	else:
		#GETTING DB
		db = "HOSREP"

#CHECKING ANSWERS
current_start_index = current_end_index + len(" find ")
current_end_index = cdal.lower().find(" for patients ", current_start_index)
if current_end_index == -1:
	error = 'Syntax Error in ANSWERS: missing FOR PATIENTS keyword'
	cdal_error_array.append(error)
else:	
	current_string = cdal[current_start_index:current_end_index].strip()

	input_answers = []
	#GETTING THE ANSWER INPUT
	answer = current_string
	#CHECKING IF ANSWER IS VALID
	answers = current_string.lower().split(",")
	
	for input_answer in answers:
		has_ref_entity = 0
		has_sta_entity = 0
		has_med_entity = 0
		
		if input_answer.find(" of ") == -1:
			error = "Syntax Error in ANSWERS: Missing keyword 'OF'"
			cdal_error_array.append(error)
			break
		input_answer_tokens = input_answer.split(" of ")
		if len(input_answer_tokens) != 2:
			error = "Syntax Error in ANSWERS: Only 1 keyword 'OF' allowed in each answer"
			cdal_error_array.append(error)
			break
		
		input_fn_parts = input_answer_tokens[0].strip().lower().split(" and ")
		for input_fn in input_fn_parts:
			for reference_entity in reference_entities:
				if input_fn == reference_entity.lower():
					has_ref_entity = 1
					break
			if has_ref_entity == 0:
				for stat_entity in stat_entities:
					if input_fn == stat_entity.lower():
						has_sta_entity = 1
						break
				if has_sta_entity == 0:
					error = "Syntax Error in ANSWERS: Missing|Incorrect ref_ent|sta_ent"
					cdal_error_array.append(error)
					break
	
		if SyntaxParser.getTerm(input_answer_tokens[1].strip().lower(), value_entities) == None:
			error = "Syntax Error in ANSWERS: Missing|Incorrect med_ent"
			cdal_error_array.append(error)
			break

has_diagnosis = 0
has_time_period = 0
has_location = 0

current_keyword = " for patients "
current_start_index = current_end_index + len(current_keyword)
current_end_index = cdal.find(" ", current_start_index)
current_string = cdal[current_start_index:current_end_index]
has_keyword = 0
for keyword in keywords:
	if current_string.lower().strip() == keyword.lower().strip():
		current_keyword = current_string
		has_keyword = 1
		break
if has_keyword == 0:
	error = "Syntax Error in CDAL: missing keyword"
	cdal_error_array.append(error)	
else:
	stop_signal = 0
	#CHECKING THE REST TOKENS OF CDAL
	#COULD BE DEMO CRITERIAS, MED CRITERIAS, DIAGNOSIS, TIME PERIOD OR LOCATION(WARD)
	while current_end_index != len(cdal):
		current_start_index = current_end_index
		current_end_index = SyntaxParser.getIndex(cdal, keywords, current_start_index)
		if current_end_index == -1:
			current_end_index = len(cdal)
			stop_signal = 1
		current_string = cdal[current_start_index:current_end_index]
		#CASE DEMO CRITERIAS
#		print current_string
		if current_keyword.upper().strip() == 'WHOSE':
			if len(current_string.strip()) == 0:
				error = 'Syntax Error in DEMO CONDITIONS: missing demo conditions'
				cdal_error_array.append(error)
			else:
# demographic criteria information
                
				patient = current_string.strip().lower()
				
		elif current_keyword.upper().strip() == 'WITH':
			if len(current_string.strip()) == 0:
				error = 'Syntax Error in MED CONDITIONS: missing med conditions'
				cdal_error_array.append(error)
			else:

# medical criteria information
				cond = current_string.strip().lower()
				
		elif current_keyword.upper().strip() == 'HAVE':
			has_diagnosis = 1
			index = current_string.lower().strip().find("diagnosis keywords of ", 0)
			if index != 0:
			    error = 'Syntax Error in DIAGNOSIS: incomplete HAVE statement'
			    cdal_error_array.append(error)
			else:
			    diagnosis_ = current_string.strip()[22: len(current_string)]
			    if diagnosis_.strip() == '':
					error = 'Syntax Error in DIAGNOSIS: missing diagnosis information'
					cdal_error_array.append(error)
			    else:

# diagnosis information
				    diagnosis = diagnosis_
		
		elif current_keyword.upper().strip() == '[DEFAULT':
			has_time_period = 0
			error = "Syntax Error in CDAL: missing time period"
			cdal_error_array.append(error)
		
		elif current_keyword.upper().strip() == "FROM":
			has_time_period = 1
			time_ent_start = current_string.strip()[0: len(current_string)]
		
		elif current_keyword.upper().strip() == "TO":
			has_time_period = 1
			time_ent_end = current_string.strip()[0: len(current_string)]	
		
		elif current_keyword.upper().strip() == 'IN':
			has_location = 1
			if len(current_string.strip()) == 0:
				error = 'Syntax Error in LOCATION: missing location'
				cdal_error_array.append(error)
			else:
                
# ward information
				ward = "HOSREP"
		
		if stop_signal == 1:
			break
			
		current_start_index = current_end_index
		current_end_index = cdal.find(" ", current_start_index + 1)
		current_keyword = cdal[current_start_index:current_end_index]

if has_time_period == 0:
	error = "Syntax Error in CDAL: missing time period"
	cdal_error_array.append(error)

if has_location == 0:
	error = "Syntax Error in CDAL: missing location"
	cdal_error_array.append(error)
	
# return the number of hrs of the query (so 1 day = 24 hrs)
#duration = SyntaxParser.toHours(time_val, time_ent)


#-------------------------END SYNTAX CHECKING FOR CDAL---------------------------------
if len(cdal_error_array) > 0: # If there are errors
    for cdal_error in cdal_error_array:
		print "<div class='cdal_error'>" + cdal_error + "</div>"

else:

	# --------------------------------------------
	
	# ----------- Print CDAL entered -------------
	print """
		<div id='cdal'>
			<div id='cdal_title'>CliniDAL entered</div>
			<div id='cdal_content'>
	"""
	print cdal
	print """
			</div>
		</div>
	"""	
	if has_diagnosis != 2:
#		"""
#        SQLGenerator prototype (terminology_server_name, hospital_database_name, patient_demo, medical_criteria, diagnosis, duration, ward)       
#        terminology_server_name: SNOMED
#        hospital_database_name: hosrep
#        patient_demo: age > 20 and age < 50 and gender = male
#        medical_criteria: diagnosis code = c32
#        diagnosis: skin
#        duration: 8736
#        ward: hosrep
		patient_cond_array = SyntaxParser.getConditions(patient, comparands, types, demo_entities)
        cond_array = SyntaxParser.getConditions(cond, comparands, types, med_entities)
        diag_array = diagnosis.split(",")

        index = answer.find("of ") + 3
        attr = answer[index:len(answer)].strip().lower()
        default_answer_array = ["request_table.patientid", "request_table.requestid", "request_table.datetime_request", "resultdetails_table.diagnosiscode", "resultdetails_table.examcode", "request_table.specimentype", "request_table.accessionnumber"]
        answer_array = default_answer_array
        if showMRN == 1:
        	answer_array.append("patient_table.mrn")
        	answer_array.append("patient_table.hospital_code")
        if default_answer_array.count(SyntaxParser.getTerm(attr, value_entities)) == 0:
        	answer_array.append(SyntaxParser.getTerm(attr, value_entities))
#        print patient_cond_array
#        print cond_array
        SQLscript = SQLGenerator.SQLGenerator(toc, db, answer_array, patient_cond_array, cond_array, time_ent_start, time_ent_end, ward)
        SQLscript.Generator()
        
#    	print "<div id='sqlscript'>SQLScript: " + SQLscript.sqlscript + " </div> "
    	
    	print "<div id='cdal_version'>CliniDAL version: " + SyntaxParser.getLatestVersion() + "</div>"
    	
    	print "<div id='results'>"
    	print "<div id='results_title'>Results (Retrieved at " + strftime("%Y-%m-%d %H:%M:%S") + ")</div>"    	
					
    	cursor = connection.cursor()  	
    	cursor.execute(SQLscript.sqlscript)
##    	
        resultset = cursor.fetchall()
        if has_diagnosis == 1:
    		import DiagMatrix
    		dm = DiagMatrix.DiagMatrix()
    		dm.getDiagMatrixInstant(diagnosis)
    		dm.getResultMatrix(cursor)
    	print "<div class='ref_answer_required'><i>" + answer + ":</i></div>"
    	if has_diagnosis == 0:
    		print "<div class='ref_answer_required'><i>" + str(len(resultset)) + " results have been retrieved.</i></div>"
#        		<div>
#        		<span>Sorted by</span>
#        		<span ><select name="mydropdown" method = "post" onchange='try.py'>
#						<option value="PID">Patient ID</option>
#						<option value="RequestDateTime" selected="selected">Request Date Time</option>
#						<option value="DiagCode">Diagnosis Code</option>
#						</select></span></div>""" 
        if has_diagnosis == 1:
        	print "<div class='ref_answer_required'><i>" + str(len(dm.result_matrix)) + " results have been retrieved.</i></div>"
    	print "<div class='ref_answer_content'>"
    	print "<table border='1'>" 
    	columnheader = "<tr>"

	pos_special = 0
    	for i in range(0, len(answer_array)):
    		if answer_array[i].split(".")[1] <> "requestid":
    			if answer_array[i].split(".")[1] == "dob":
    				pos_special = i
    			columnheader = columnheader + "<th>" + answer_array[i].split(".")[1] + "</th>"
    		else:
    			pos = i
    	if has_diagnosis == 1:
    		columnheader = columnheader + "<th id='wrap'>historical accession number(s)</th>"
    	columnheader = columnheader + "</tr>"
    	print columnheader

    	for tuple in resultset:
    		column = ""
    		if has_diagnosis == 0:
	    		column = "<tr>"
	    		for i in range(0, len(tuple)):
	    			if i <> pos:
	    				if i == pos_special and pos_special != 0:
	    					if tuple[0] <> None:
	    						column = column + "<td>" + SyntaxParser.transformDOBtoAge(str(tuple[i])) + "</td>"
	    				else:
	    					column = column + "<td>" + str(tuple[i]) + "</td>"
    		if has_diagnosis == 1:
    			if dm.result_matrix.has_key(tuple[0]):
    				if dm.result_matrix[tuple[0]].count(tuple[1]) != 0:
		    			column = "<tr>"
		    			for i in range(0,len(tuple)):
		    				if i <> pos:
		    					if i == pos_special and pos_special != 0:
	    							if tuple[0] <> None:
	    								column = column + "<td>" + SyntaxParser.transformDOBtoAge(str(tuple[i])) + "</td>"
	    						else:
	    							column = column + "<td>" + str(tuple[i]) + "</td>"
		    			column = column + "<td id='wrap'>"
		    			for i, reqid in enumerate(dm.result_matrix[tuple[0]]):
		    				column = column + str(accession_dic[reqid])
		    				if i < len(dm.result_matrix[tuple[0]]) -1:
		    					column = column + ","
		    			column = column + "</td>"
		    			column = column + "</tr>"
    		print column
				
        print "</div>" #Closing div 'Results'
        print "</body></html>"
        
